# -*- coding:utf-8 -*-
from utils.views import WdListCreateAPIView, WdRetrieveUpdateAPIView, WdAPIView, WdDestroyAPIView, WdListAPIView
from manufacturer.models import ElevatorMalfunction, ElevatorMalfunctionPersonRelation, ElevatorMalfunctionDeal, \
    RepairContent, AuthorityCode, RepairContentElevatorMalfunctionRelation, ElevatorStatus, ElevatorWarning, ElevatorFault
from manufacturer.serializer import AppElevatorMalfunctionListSerializer, AppElevatorMalfunctionDetailSerializer, \
    AppElevatorMalfunctionSerializer, StatusMonitorAppListSerializer, AppElevatorWarningSerializer
from utils.response import ErrorCode, general_json_response
import datetime
from rest_framework import status
from basic.models import ElevatorInfo
import json
from django.db.models import Q
import operator
from utils.logger import get_logger
logger = get_logger(__name__)


def get_registers(user):
    u""" 非各个角色的管理员才会调用 """
    from users.models import OrganizationElevatorRelation, OrganizationAdminRoRelation, ElevatorAdminRoRelation, \
        AuthUserElevatorRelation
    if user.permission_type == 20:
        codes = AuthUserElevatorRelation.objects.filter_active(auth_user=user).values_list("register_code", flat=True).distinct()
        return codes
    admin_role = user.admin_role
    codes = list()
    if not admin_role:
        return codes
    if admin_role.management_type == 20:
        codes = ElevatorAdminRoRelation.objects.filter_active(admin_role=admin_role).values_list("register_code", flat=True).distinct()
        return codes
    oarr = OrganizationAdminRoRelation.objects.filter_active(admin_role=admin_role).first()
    if not oarr:
        return codes
    org = oarr.organization
    if not org:
        return codes
    codes = OrganizationElevatorRelation.objects.filter_active(organization=org).values_list("register_code", flat=True).distinct()
    return codes


class AppElevatorMalfunctionListView(WdListCreateAPIView):
    model = ElevatorMalfunction
    serializer_class = AppElevatorMalfunctionDetailSerializer
    p_serializer_class = AppElevatorMalfunctionSerializer
    POST_DATA_ID_RESPONSE = True
    POST_DATA_RESPONSE = True
    FILTER_FIELDS = ("status", )

    def qs_filter(self, qs):
        qs = super(AppElevatorMalfunctionListView, self).qs_filter(qs)
        user = self.request.user
        print "user.role: %s" % user.role
        if user.role == 10:
            person = user.person
            ids = ElevatorMalfunctionPersonRelation.objects.filter_active(person=person).\
                values_list("elevator_malfunction_id", flat=True).distinct()
            qs = qs.filter(id__in=ids)
        elif user.role == 30:
            company = user.company_person.company
            qs = qs.filter(property_company=company, status__in=(10, 50))
        return qs

    def post_check_parameter(self, kwargs):
        code = super(AppElevatorMalfunctionListView, self).post_check_parameter(kwargs)
        if code != ErrorCode.SUCCESS:
            return code
        user = self.request.user
        qr_code = self.request.data.pop("qr_code", None)
        if qr_code:
            e = ElevatorInfo.objects.filter_active(qr_code=qr_code).first()
            if not e:
                code = ErrorCode.QRCODE_NOT_EXISTED
                return code
        register_code = self.request.data.get("register_code", None)
        if register_code:
            e = ElevatorInfo.objects.filter_active(register_code=register_code).first()
            if not e:
                code = ErrorCode.REGISTER_CODE_NOT_EXISTED
                return code
        now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        time_points = json.dumps({"0": now})
        pro_no = e.factory_no
        ac = AuthorityCode.objects.filter_active(elevator_code=e.register_code).first()
        factory_code = ac.manufacturer_code if ac else None
        per_unique_code = ac.device_code if ac else None
        alarm_time = datetime.date.today()
        self.request.data.update({
            "create_user": user.id,
            "register_code": e.register_code,
            "pro_no": pro_no,
            "factory_code": factory_code,
            "per_unique_code": per_unique_code,
            "alarm_time": now,
            "status": 0,
            "elevator": e.id,
            "service_id": e.service_id,
            "time_points": time_points,
            "maintain_company": e.maintain_company.id,
            "property_company": e.property_company.id,
            "maintain_company_name": e.maintain_company.name,
            "property_company_name": e.property_company.name,
        })
        return code

    def perform_create(self, serializer):
        create_obj = serializer.save()
        elevator_malfunction_id = serializer.data.get("id")
        content = self.request.data.get("content", []) # [{"repair_content_id": xx, "number": 4}, {}]
        service_id = serializer.data.get("service_id", 0)
        buck_list = list()
        money = 0
        for c in content:
            obj = RepairContentElevatorMalfunctionRelation(elevator_malfunction_id=elevator_malfunction_id,
                                                           service_id=service_id, repair_content_id=c["repair_content_id"],
                                                           number=c["number"])
            m = obj.repair_content.content_costs.all().first()
            if m:
                money += m.costs
            buck_list.append(obj)
        RepairContentElevatorMalfunctionRelation.objects.bulk_create(buck_list)
        create_obj.costs = money
        create_obj.save()


class AppElevatorMalfunctionDetailView(WdRetrieveUpdateAPIView):
    model = ElevatorMalfunction
    serializer_class = AppElevatorMalfunctionDetailSerializer
    p_serializer_class = AppElevatorMalfunctionSerializer
    POST_DATA_RESPONSE = True
    POST_DATA_ID_RESPONSE = True

    def post_check_parameter(self, kwargs):
        code = super(AppElevatorMalfunctionDetailView, self).post_check_parameter(kwargs)
        if code != ErrorCode.SUCCESS:
            return code
        s = self.request.data.get("status", None)
        n = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        obj = self.get_object()
        now = datetime.datetime.now().date()
        time_points = self.get_object().time_points
        user = self.request.user
        emfd = ElevatorMalfunctionDeal.objects.filter_active(elevator_malfunction_id=obj.id).exclude(status=30).first()

        d = dict(self.request.data)
        d = json.dumps(d)
        logger.info(d)

        if s and s == 20:   # 物业确认
            if time_points:
                tp = json.loads(time_points)
                tp.update({"20": n})
            else:
                tp = {"20": n}
            self.request.data.update({"time_points": json.dumps(tp)})

            ElevatorMalfunctionDeal.objects.get_or_create(register_code=obj.register_code, elevator_id=obj.elevator_id,
                                                          send_person=obj.notify_person, jecv_time=now,
                                                          alarm_time=obj.alarm_time, status=20,
                                                          service_id=obj.service_id,
                                                          defaults={"elevator_malfunction_id": self.get_id()})
        if s and s == 30:    # 维修人员拒绝
            if time_points:
                tp = json.loads(time_points)
                tp.update({"30": n})
            else:
                tp = {"30": n}
            self.request.data.update({"time_points": json.dumps(tp)})
            jecv_time = emfd.jecv_time if emfd else now
            ElevatorMalfunctionDeal.objects.create(elevator_malfunction_id=self.get_id(), service_id=obj.service_id,
                                                   register_code=obj.register_code, elevator_id=obj.elevator_id,
                                                   send_person=obj.notify_person, jecv_time=jecv_time,
                                                   recv_person=user.real_name, alarm_time=obj.alarm_time, status=30)
            empr = ElevatorMalfunctionPersonRelation.objects.filter_active(person=user.person, elevator_malfunction_id=obj.id).first()
            if empr:
                empr.is_active = False
                empr.save()
        if s and s == 40:     # 到达现场
            if time_points:
                tp = json.loads(time_points)
                tp.update({"40": n})
            else:
                tp = {"40": n}
            self.request.data.update({"time_points": json.dumps(tp)})
            emfd.status = 40
            emfd.save()
        if s and s == 50:  # 维修完成
            if time_points:
                tp = json.loads(time_points)
                tp.update({"50": n})
            else:
                tp = {"50": n}
            self.request.data.update({"time_points": json.dumps(tp)})
            content = self.request.data.get("content", [])  # [{"repair_content_id": xx, "number": 4}, {}]
            signature = self.request.data.pop("signature", None)
            work_hours = self.request.data.get("work_hours_success", None)
            desc = self.request.data.pop("desc", None)
            solution = self.request.data.get("solution", None)
            emfd.signature = signature
            emfd.status = 50
            emfd.work_hours = work_hours
            emfd.desc = desc
            emfd.solution = solution
            emprs = ElevatorMalfunctionPersonRelation.objects.filter_active(elevator_malfunction_id=obj.id)
            names = ""
            for e in emprs:
                names += e.get_username()
            emfd.recv_person = names

            elevator_malfunction_id = self.get_id()
            service_id = self.get_object().service_id
            cs = RepairContentElevatorMalfunctionRelation.objects.filter_active(
                elevator_malfunction_id=elevator_malfunction_id).values("repair_content_id", "number")
            money = 0
            if sorted(content) != sorted(cs):
                RepairContentElevatorMalfunctionRelation.objects.filter_active(
                    elevator_malfunction_id=elevator_malfunction_id).update(is_active=False)
                buck_list = list()
                for c in content:
                    obj = RepairContentElevatorMalfunctionRelation(elevator_malfunction_id=elevator_malfunction_id,
                                                                   service_id=service_id, number=c["number"],
                                                                   repair_content_id=c["repair_content_id"])
                    buck_list.append(obj)
                    m = obj.repair_content.content_costs.all().first()
                    if m:
                        money += m.costs * c["number"]
                if buck_list:
                    RepairContentElevatorMalfunctionRelation.objects.bulk_create(buck_list)
            else:
                money = self.get_object().costs
            emfd.costs = money
            emfd.save()
            self.request.data.update({"actual_costs": money})
        if s and s == 60:
            if time_points:
                tp = json.loads(time_points)
                tp.update({"60": n})
            else:
                tp = {"60": n}
            self.request.data.update({"time_points": json.dumps(tp)})
            emfd.status = 60
            emfd.save()

        if s and s == 70:
            if time_points:
                tp = json.loads(time_points)
                tp.update({"70": n})
            else:
                tp = {"70": n}
            self.request.data.update({"time_points": json.dumps(tp)})
            signature = self.request.data.pop("signature", None)
            if signature:
                emfd.signature = signature
            emfd.status = 70
            emfd.save()
        return code

    def put(self, request, *args, **kwargs):
        if self.p_serializer_class is not None:
            self.serializer_class = self.p_serializer_class
        if self.partial:
            rsp = self.partial_update(request, *args, **kwargs)
        else:
            rsp = self.update(request, *args, **kwargs)
        pic_success = self.request.data.get("pic_success", None)
        if pic_success:
            emfd = ElevatorMalfunctionDeal.objects.filter_active(elevator_malfunction_id=self.get_id()).first()
            emfd.pic_success = pic_success
            emfd.save()
        if self.POST_DATA_RESPONSE:
            return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, rsp.data)
        else:
            return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS)


class QueryRepairContentView(WdAPIView):

    def get(self, request, *args, **kwargs):
        person = self.request.user.person
        rcs = RepairContent.objects.filter_active(service_id__in=(person.service_id, 0))
        content = self.request.GET.get("content", None)
        if content:
            rcs = rcs.filter(content__icontains=content)
        data = [rc.to_json() for rc in rcs]
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, data)


class ElevatorStatusListAppView(WdListAPIView):

    # model = ElevatorStatus
    model = AuthorityCode
    serializer_class = StatusMonitorAppListSerializer
    SEARCH_FIELDS = ("elevator_code", "manufacturer_number_elevator", "property_company_name", "address", "device_code_elevator")

    def qs_filter(self, qs):
        qs = super(ElevatorStatusListAppView, self).qs_filter(qs)
        l = ElevatorInfo.objects.filter_active(~Q(factory_no=''), manufacturer_company__isnull=False)
        user = self.request.user
        if user.role == 0:
            pass
        elif user.role in (10, 20, 30, 40):
            service_id = user.service_id
            l = l.filter(service_id=service_id)
            if user.role == 10 or not user.company_person.is_admin:
                codes = get_registers(user)
                l = l.filter(register_code__in=codes)
        else:
            l = l.none()
        m = []
        for ei in l:
            m.append({"manufacturer_code": ei.manufacturer_company.code, "manufacturer_number": ei.factory_no})
        ids = []
        for dic in m:
            ac = AuthorityCode.objects.filter_active(manufacturer_code_elevator=dic['manufacturer_code'], manufacturer_number_elevator=dic['manufacturer_number']).first()
            if ac:
                ids.append(ac.id)
        qs = qs.filter(id__in=ids)
        is_online = self.request.GET.get("is_online", None)
        if is_online == "1":
            qs = qs.filter(is_online=True)
        elif is_online == "0":
            qs = qs.filter(is_online=False)
        return qs

    def qs_business_role(self, qs):
        return qs


class ElevatorStatusDetailAppView(WdAPIView):

    def get(self, request, *args, **kwargs):
        elevator_id = self.request.GET.get("elevator_id", None)
        status_id = self.request.GET.get("status_id", None)
        d = json.dumps(dict(self.request.GET))
        logger.info(d)
        es = None
        ac = None
        ei = None
        if elevator_id:
            logger.info("elevator_id")
            logger.info(elevator_id)
            logger.info(type(elevator_id))
            ei = ElevatorInfo.objects.filter_active(id=int(elevator_id)).first()
            if ei:
                ac = AuthorityCode.objects.filter_active(manufacturer_code_elevator=ei.manufacturer_company.code, manufacturer_number_elevator=ei.factory_no).first()
                if ac:
                    es = ElevatorStatus.objects.filter_active(o=ac.device_code_elevator).first()
        elif status_id:
            logger.info("status_id")
            logger.info(status_id)
            logger.info(type(status_id))
            # es = ElevatorStatus.objects.filter_active(id=int(status_id)).first()
            ac = AuthorityCode.objects.filter_active(id=int(status_id)).first()
            if ac:
                es = ElevatorStatus.objects.filter_active(o=ac.device_code_elevator).first()
                if es:
                    ei = ElevatorInfo.objects.filter_active(manufacturer_company__code=ac.manufacturer_code_elevator, factory_no=ac.manufacturer_number_elevator).first()
        # ac = AuthorityCode.objects.filter_active(elevator_code=register_code).first()
        data = {"register_code": ei.register_code if ei else None, "internal_no": ei.internal_no if ei else None, "address": ac.address if ac else None,
                "manufacturer_company_name": ac.manufacturer_name() if ac else None, "ps": None, "run_status": None,
                "property_company_name": ac.property_company_name if ac else None, "is_open": None, "rt": None, "rc": None}

        rt = 0
        jrt = 0
        up_time = 0
        pc = None
        is_open = 0
        lc = 0
        run_status = 0
        zr = u"未知"
        lm = ""
        h = 0
        jh = 0
        warn = ""
        if ac and ac.device_code_elevator:
            rt = ac.run_times
            jrt = ac.run_times - ac.yesterday_run_times
            up_time = ac.up_time
            # es = ElevatorStatus.objects.filter_active(o=ac.device_code_elevator).order_by("-id").first()
            if es:
                is_open = es.is_open()
                lc = es.cp
                run_status = es.run_status()
                if es.ol == "1":
                    zr = u"超载"
                elif es.fl == "1":
                    zr = u"满载"
                elif es.ps == "1":
                    zr = u"有人"
                elif es.ps == "0":
                    zr = u"无人"
                else:
                    zr = u"未知"
                if es.dz == "1":
                    pc = u"平层"
                elif es.dz == "0":
                    pc = u"非平层"
                if es.lm:
                    lm = es.get_lm_display()
                else:
                    lm = u"未知"
            ef = ElevatorFault.objects.filter_active(o=ac.device_code_elevator).order_by("-id").first()

            alarms = {"1": u"轿厢报警按钮", "2": u"电梯困人", "3": u"非平层停梯", "4": u"安全回路断路", "5": u"轿厢冲顶",
                      "6": u"轿厢蹲底", "7": u"开门走梯", "8": u"电梯速度异常"}
            if ef and ef.a:
                warn = ",".join([alarms[k] for k in ef.a.split(",") if k in alarms])
            yesterday_up_time = ac.yesterday_up_time

            h = up_time / 3600
            d_time = up_time - yesterday_up_time
            jh = d_time / 3600

        data['rt'] = rt              # 运行次数
        data['jrt'] = jrt              # 今日运行次数
        data['up_time'] = up_time
        data['pc'] = pc              # 平层
        data['is_open'] = is_open   #
        data['lc'] = lc              # 楼层
        data['run_status'] = run_status
        data['zr'] = zr                 # 载人状态 返回的是汉字 小胖你不用判断了，直接用这个字符串既可
        data['lm'] = lm                 # 电梯模式
        data['km'] = ac.open_times if ac else None    # 开关门次数
        data['jkm'] = ac.open_times - ac.yesterday_open_times if ac else None     # 今日开关门次数
        data['h'] = h                   # 运行小时
        data['jh'] = jh                 # 今日 运行小时
        data['warn'] = warn             # 最后一次警告 字符串
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, data)


class ElevatorWarningListAppView(WdListAPIView):

    model = ElevatorFault
    serializer_class = AppElevatorWarningSerializer
    FILTER_FIELDS = ("s", )

    def qs_filter(self, qs):
        qs = super(ElevatorWarningListAppView, self).qs_filter(qs)
        time_from = self.request.GET.get("time_from", None)
        time_to = self.request.GET.get("time_to", None)
        user = self.request.user
        if user.role == 10:
            service_id = user.service_id
            aos = AuthorityCode.objects.filter_active(maintain_company_id=service_id).values_list("device_code_elevator", flat=True).distinct()
        elif user.role == 30:
            service_id = user.company_person.company.service_id
            aos = AuthorityCode.objects.filter_active(maintain_company_id=service_id).values_list("device_code_elevator", flat=True).distinct()
        else:
            aos = list()

        qs = qs.filter(o__in=aos)
        if time_from and time_to:
            qs = qs.filter(create_time__gte=time_from, create_time__lte=time_to)
        elif time_to and not time_from:
            qs = qs.filter(create_time__lte=time_to)
        elif time_from and not time_to:
            qs = qs.filter(create_time__gte=time_from)
        return qs

    def qs_business_role(self, qs):
        return qs


class AppElevatorStatusStatisticsView(WdAPIView):

    def get(self, request, *args, **kwargs):
        l = ElevatorInfo.objects.filter_active(~Q(factory_no=''), manufacturer_company__isnull=False)
        user = self.request.user
        if user.role == 0:
            pass
        elif user.role in (10, 20, 30, 40):
            service_id = user.service_id
            l = l.filter(service_id=service_id)
            if user.role == 10 or not user.company_person.is_admin:
                codes = get_registers(user)
                l = l.filter(register_code__in=codes)
        else:
            l = l.none()
        m = []
        for ei in l:
            m.append({"manufacturer_code": ei.manufacturer_company.code, "manufacturer_number": ei.factory_no})
        ids = []
        for dic in m:
            ac = AuthorityCode.objects.filter_active(manufacturer_code_elevator=dic['manufacturer_code'],
                                                     manufacturer_number_elevator=dic['manufacturer_number']).first()
            if ac:
                ids.append(ac.id)

        acs_o_on = AuthorityCode.objects.filter_active(id__in=ids, is_online=True).values_list("device_code_elevator", flat=True).distinct()
        acs_o_off = AuthorityCode.objects.filter_active(id__in=ids, is_online=False).values_list("device_code_elevator", flat=True).distinct()
        online_count = acs_o_on.count()
        offline_count = acs_o_off.count()

        user = self.request.user
        if user.role == 10:
            service_id = user.service_id
            aos = AuthorityCode.objects.filter_active(maintain_company_id=service_id).values_list(
                "device_code_elevator", flat=True).distinct()
        elif user.role == 30:
            service_id = user.company_person.company.service_id
            aos = AuthorityCode.objects.filter_active(maintain_company_id=service_id).values_list(
                "device_code_elevator", flat=True).distinct()
        else:
            aos = list()

        warning = ElevatorFault.objects.filter_active(s='e', o__in=aos).count()
        warning_all = ElevatorFault.objects.filter_active(o__in=aos).count()
        data = {
            "online_count": online_count,
            "offline_count": offline_count,
            "warning": warning,
            "warning_all": warning_all
        }
        return general_json_response(status.HTTP_200_OK, ErrorCode.SUCCESS, data)




































